﻿/*
** Haaf's Game Engine 1.5
** Copyright (C) 2003-2004, Relish Games
** hge.relishgames.com
**
** hgeDistortionMesh helper class header
*/


module core.hgedistort;

private import core.hgeall;


const HGEDISP_NODE			=0;
const HGEDISP_TOPLEFT		=1;
const HGEDISP_CENTER		=2;

/*
** HGE Distortion mesh class
*/
class hgeDistortionMesh
{

public:
	this(int cols, int rows)
	{
		int i;
		
		hge=gameInfo.hge;

		nRows=rows;
		nCols=cols;
		cellw=cellh=0;
		quad.tex=0;
		quad.blend=BLEND_COLORMUL | BLEND_ALPHABLEND | BLEND_ZWRITE;
		disp_array=new hgeVertex[rows*cols];

		for(i=0;i<rows*cols;i++)
		{
			disp_array[i].x=0.0f;
			disp_array[i].y=0.0f;
			disp_array[i].tx=0.0f;
			disp_array[i].ty=0.0f;
			
			disp_array[i].z=0.5f;
			disp_array[i].col=0xFFFFFFFF;
		}
	}


	this(inout  hgeDistortionMesh dm)
	{
		hge=gameInfo.hge;

		nRows=dm.nRows;
		nCols=dm.nCols;
		cellw=dm.cellw;
		cellh=dm.cellh;
		tx=dm.tx;
		ty=dm.ty;
		width=dm.width;
		height=dm.height;
		quad=dm.quad;

		disp_array=new hgeVertex[nRows*nCols];
		disp_array[]=dm.disp_array[0..nRows*nCols];
		//memcpy(disp_array, dm.disp_array, sizeof(hgeVertex)*nRows*nCols);
	}


	~this()
	{
		delete disp_array;
	}

	hgeDistortionMesh  opaAddAssign ( hgeDistortionMesh dm)
	{
		if(this!=dm)
		{
			nRows=dm.nRows;
			nCols=dm.nCols;
			cellw=dm.cellw;
			cellh=dm.cellh;
			tx=dm.tx;
			ty=dm.ty;
			width=dm.width;
			height=dm.height;
			quad=dm.quad;

			delete disp_array;
			disp_array=new hgeVertex[nRows*nCols];
			disp_array[]=dm.disp_array[0..nRows*nCols];
			//memcpy(disp_array, dm.disp_array, sizeof(hgeVertex)*nRows*nCols);
		}

		return this;
		
	}


	void 	Render(float x, float y)
	{
		int i,j,idx;

		for(j=0; j<nRows-1; j++)
			for(i=0; i<nCols-1; i++)
			{
				idx=j*nCols+i;

				quad.v[0].tx=disp_array[idx].tx;
				quad.v[0].ty=disp_array[idx].ty;
				quad.v[0].x=x+disp_array[idx].x;
				quad.v[0].y=y+disp_array[idx].y;
				quad.v[0].z=disp_array[idx].z;
				quad.v[0].col=disp_array[idx].col;

				quad.v[1].tx=disp_array[idx+1].tx;
				quad.v[1].ty=disp_array[idx+1].ty;
				quad.v[1].x=x+disp_array[idx+1].x;
				quad.v[1].y=y+disp_array[idx+1].y;
				quad.v[1].z=disp_array[idx+1].z;
				quad.v[1].col=disp_array[idx+1].col;

				quad.v[2].tx=disp_array[idx+nCols+1].tx;
				quad.v[2].ty=disp_array[idx+nCols+1].ty;
				quad.v[2].x=x+disp_array[idx+nCols+1].x;
				quad.v[2].y=y+disp_array[idx+nCols+1].y;
				quad.v[2].z=disp_array[idx+nCols+1].z;
				quad.v[2].col=disp_array[idx+nCols+1].col;

				quad.v[3].tx=disp_array[idx+nCols].tx;
				quad.v[3].ty=disp_array[idx+nCols].ty;
				quad.v[3].x=x+disp_array[idx+nCols].x;
				quad.v[3].y=y+disp_array[idx+nCols].y;
				quad.v[3].z=disp_array[idx+nCols].z;
				quad.v[3].col=disp_array[idx+nCols].col;

				hge.Gfx_RenderQuad(&quad);
			}
	}







	 
    void	Clear(uint col=0xFFFFFFFF, float z=0.5f)
	{
		int i,j;

		for(j=0; j<nRows; j++)
			for(i=0; i<nCols; i++)
			{
				disp_array[j*nCols+i].x=i*cellw;
				disp_array[j*nCols+i].y=j*cellh;
				disp_array[j*nCols+i].col=col;
				disp_array[j*nCols+i].z=z;
			}
	}

	void  	SetTexture(HTEXTURE tex)
	{
		quad.tex=tex;
	}




	void 	SetTextureRect(float x, float y, float w, float h)
	{
		int i,j;
		float tw,th;

		tx=x; ty=y; width=w; height=h;

		if (quad.tex)
		{
			tw=cast(float)hge.Texture_GetWidth(quad.tex);
			th=cast(float)hge.Texture_GetHeight(quad.tex);
		}
		else
		{
			tw = w;
			th = h;
		}

		cellw=w/(nCols-1);
		cellh=h/(nRows-1);

		for(j=0; j<nRows; j++)
			for(i=0; i<nCols; i++)
			{
				disp_array[j*nCols+i].tx=(x+i*cellw)/tw;
				disp_array[j*nCols+i].ty=(y+j*cellh)/th;

				disp_array[j*nCols+i].x=i*cellw;
				disp_array[j*nCols+i].y=j*cellh;
			}
	}











	 

	void SetBlendMode(int blend)
	{
		quad.blend=blend;
	}


	void SetZ(int col, int row, float z)
	{
		if(row<nRows && col<nCols) disp_array[row*nCols+col].z=z;
	}

	

	void SetColor(int col, int row, uint color)
	{
		if(row<nRows && col<nCols) disp_array[row*nCols+col].col=color;
	}


	void SetDisplacement(int col, int row, float dx, float dy, int ref__)
	{
		if(row<nRows && col<nCols)
		{
			switch(ref__)
			{
				case HGEDISP_NODE:		dx+=col*cellw; dy+=row*cellh; break;
				case HGEDISP_CENTER:	dx+=cellw*(nCols-1)/2;dy+=cellh*(nRows-1)/2; break;
				case HGEDISP_TOPLEFT:	break;
				default	: break;
			}

			disp_array[row*nCols+col].x=dx;
			disp_array[row*nCols+col].y=dy;
		}
	}





	 

     HTEXTURE	GetTexture()  {return quad.tex;}
     void		GetTextureRect(float *x, float *y, float *w, float *h)  { *x=tx; *y=ty; *w=width; *h=height; }
     int		GetBlendMode()  { return quad.blend; }

	float GetZ(int col, int row)
	{
		if(row<nRows && col<nCols) return disp_array[row*nCols+col].z;
		else return 0.0f;
	}





	uint GetColor(int col, int row) 
	{
		if(row<nRows && col<nCols) return disp_array[row*nCols+col].col;
		else return 0;
	}


	void GetDisplacement(int col, int row, inout float dx, inout float dy, int ref_) 
	{
		if(row<nRows && col<nCols)
		{
			switch(ref_)
			{
				case HGEDISP_NODE:		dx=disp_array[row*nCols+col].x-col*cellw;
										dy=disp_array[row*nCols+col].y-row*cellh;
										break;

				case HGEDISP_CENTER:	dx=disp_array[row*nCols+col].x-cellw*(nCols-1)/2;
										dy=disp_array[row*nCols+col].x-cellh*(nRows-1)/2;
										break;

				case HGEDISP_TOPLEFT:	dx=disp_array[row*nCols+col].x;
										dy=disp_array[row*nCols+col].y;
										break;
				default	: break;
			}
		}
	}

	 

	 int		GetRows() { return nRows; }
	 int		GetCols() { return nCols; }

private:
	this(){};

static	ifHge	hge;


	hgeVertex[]	disp_array;
	int			nRows, nCols;
	float		cellw,cellh;
	float		tx,ty,width,height;
	hgeQuad		quad;
}
